// disable randomised task struct (Linux 4.13)
#define randomized_struct_fields_start  struct {
#define randomized_struct_fields_end    };

#include "bpf.h"
#include <linux/version.h>
#include "bpf_helpers.h"

typedef struct sock_key {
    __u32 remote_ip;
    __u32 remote_port;
    __u32 local_ip;
    __u32 local_port;
} sock_key;

struct bpf_map_def SEC("maps") sock_map = {
    .map_type = BPF_MAP_TYPE_SOCKHASH,
    .key_size = sizeof(sock_key),
    .value_size = sizeof(unsigned int),
    .max_entries = 2<<10,
};

struct bpf_map_def SEC("maps") proxy_map = {
    .map_type = BPF_MAP_TYPE_HASH,
    .key_size = sizeof(int),
    .value_size = sizeof(int),
    .max_entries = 2<<10,
};

#define DEBUG 1
#ifdef DEBUG
/* Only use this for debug output. Notice output from bpf_trace_printk()
 * end-up in /sys/kernel/debug/tracing/trace_pipe
 */
#define bpf_debug(fmt, ...)                                            \
    ({                                                                 \
        char ____fmt[] = fmt;                                          \
        bpf_trace_printk(____fmt, sizeof(____fmt), ##__VA_ARGS__);     \
    })
#else
#define bpf_debug(fmt, ...){;}
#endif


SEC("sk_skb/stream_parser")
int prog_parser(struct __sk_buff *skb)
{
    int k = 2;
    int v = 2;
    bpf_map_update_elem(&proxy_map, &k, &v, 0);
    return skb->len;
}

SEC("sk_skb/stream_verdict")
int prog_verdict(struct __sk_buff *skb)
{
    struct sock_key key = {
        .remote_ip = skb->remote_ip4,
        .remote_port = skb->remote_port,
        .local_ip = skb->local_ip4,
        .local_port = skb->local_port,
    };
    int k = 2;
    int *v = 0;
    v = bpf_map_lookup_elem(&proxy_map, &k);
    if (v) {
        bpf_debug("value ret %ld\n", *v);
    }
    return bpf_sk_redirect_hash(skb, &sock_map, &key, 0);
}

char _license[] SEC("license") = "GPL";
__u32 _version SEC("version") = LINUX_VERSION_CODE;